#include "ImageDisplay.h"

std::condition_variable haveNewImage;
std::atomic<bool> newImageFlag;

std::mutex ImageDisplay::mutAsyncing;
std::atomic<bool> ImageDisplay::atomExists = true;

void imageHandler(ImageDisplay* ptr)
{
	wxImage imageI;
	unsigned char* imagePtr;
	newImageFlag = true;
	while (ptr->threadRunFlag.load())
	{
		{
			std::unique_lock lck(ptr->mutInput);
			haveNewImage.wait(lck, [&] {
				if (newImageFlag.load() || !ptr->threadRunFlag.load())
				{
					newImageFlag.store(false);
					return true;
				}
				else
				{
					return false;
				}
			}); //等待新的图像进来
		}
		if(ptr->imageUploadFlag.load())
			ptr->remotehandle->SetImage(ptr->image,ptr->height,ptr->width,ptr->format);
    switch(ptr->format)
    {
      case pixelFormat::MONO8:
		    imagePtr = ptr->imageConver.HandleImage(ptr->image,ptr->height*ptr->width);
        break;
      case pixelFormat::BAYER_RG8:
        imagePtr=ptr->imageConver.HandleBayerImage(ptr->image,ptr->width,ptr->height);
        break;
      default:
        throw;
        break;
    }
		imageI.SetData(imagePtr, ptr->width, ptr->height, false);
		{
			std::lock_guard lck(ptr->mutOutput);
			if (imageI.IsOk())
				ptr->bitmap = imageI;
		}
	}
}

ImageDisplay::ImageDisplay(wxWindow* parent, wxWindowID winID,RemoteHandle* remoteHandle) :
	wxPanel(parent, winID), image(nullptr),lastSize(10,10),webMonitor(this,remoteHandle),remotehandle(remoteHandle)
{
	image=new unsigned char[100];
	refreshTimer = new wxTimer(this, (int)ImageDisplayID::refreshTimer);
	threadRunFlag.store(true);
	imageHandleThread = std::thread(imageHandler, this);
	refreshTimer->Start(100);
	Bind(EVT_WSMONITOR,&ImageDisplay::on_WSclose_event,this,wxID_ANY);
	Bind(EVT_MULTIWRITE_ERR,&ImageDisplay::on_FileError,this,wxID_ANY);
	Bind(EVT_FILE_ERROR,&ImageDisplay::on_FileError,this,wxID_ANY);
	Bind(wxEVT_PAINT, &ImageDisplay::OnPaint, this, wxID_ANY);
	Bind(wxEVT_TIMER, &ImageDisplay::onTimerOut, this, (int)ImageDisplayID::refreshTimer);
}

ImageDisplay::~ImageDisplay()
{
	std::lock_guard lckInput(mutAsyncing);
	atomExists.store(false);
	threadRunFlag.store(false);
	haveNewImage.notify_all();
	refreshTimer->Stop();
	imageHandleThread.join();
	delete [] image;
	delete refreshTimer;
}

void ImageDisplay::showImage(const unsigned char* _image, int _width, int _height,pixelFormat _format)
{
	{
		std::unique_lock lck(mutInput);
		if(_width*_height > width*height)
		{ //图像数据缓冲不够大
			delete [] image;
			image=new unsigned char[_width*_height];
		}
		std::memcpy(image,_image,_width*_height);
		width = _width;
		height = _height;
    format=_format;
		newImageFlag.store(true);
	}
	haveNewImage.notify_one();
}

void ImageDisplay::OnPaint(wxPaintEvent& e)
{
	static int offsetX = 0, offsetY = 0;
	wxBufferedPaintDC dc(this);
	std::lock_guard lck(mutOutput);
	wxSize currentSize = bitmap.GetSize();
	if (currentSize.x != lastSize.x || currentSize.y != lastSize.y)
	{
		offsetX = GetSize().x / 2 - currentSize.x / 2;
		offsetY = GetSize().y / 2 - currentSize.y / 2;
		lastSize.x=currentSize.x;
		lastSize.y=currentSize.y;
		dc.Clear();
	}
	dc.DrawBitmap(bitmap, wxPoint(offsetX, offsetY),false);
}

void ImageDisplay::onTimerOut(wxTimerEvent& e)
{
	Refresh(false);
}

void ImageDisplay::showBitmap(const wxBitmap& sourceBit)
{
	bitmap=sourceBit;
	Refresh(true);
}

void ImageDisplay::StaticDisplay(bool b)
{
	if(!b && !refreshTimer->IsRunning())
	{
		refreshTimer->Start(100);
	}
	else if(b && refreshTimer->IsRunning())
	{
		refreshTimer->Stop();
	}
}

void ImageDisplay::on_FileError(wxCommandEvent& event)
{
	wxMessageBox(wxT("图像写入磁盘错误"),wxT("错误"),wxICON_ERROR | wxOK);
	remotehandle->SendMessage("图像写入磁盘错误");
}

void ImageDisplay::SetRemoteParameter()
{
	webMonitor.ShowSettingDialog(this);
}

bool ImageDisplay::SetRemoterMirror(bool value)
{
	if(value)
	{
		try
		{
			webMonitor.LoginServer();
		}
		catch(const std::exception& e)
		{
			wxMessageBox(wxString().FromUTF8(e.what()),wxT("连接错误"),wxICON_ERROR | wxOK);
			return false;
		}
		imageUploadFlag=true;
	}
	else
		imageUploadFlag=false;
	return true;
}

void ImageDisplay::on_WSclose_event(WSMonitorEvent& event)
{
	switch (event.GetStatus())
	{
	case 1:
		wxMessageBox(wxT("与服务器连接断开"),wxT("信息"),wxICON_INFORMATION | wxOK);
		break;
	
	default:
		wxMessageBox(wxT("未知的异常"),wxT("消息"),wxICON_INFORMATION | wxOK);
		break;
	}
}

void ImageDisplay::SetRemoteParameter(std::string IPAddress,std::string Port,std::string DeviceName)
{
	webMonitor.SetServerConfig(IPAddress,Port,DeviceName);
}
